/*
 * Item.cpp
 *
 *  Created on: 2013. 9. 10.
 *      Author: jjaehuny
 */

#include "Item.h"
#include "Static.h"

#include <Database/Static.h>

#include "../Enum.h"
#include "../User.h"

#include "../xldata/item_class1.h"
#include "../xldata/item_class2.h"
#include "../xldata/item_class3.h"
#include "../xldata/item_class4.h"
#include "../xldata/item_class5.h"
#include "../xldata/item_class6.h"
#include "../xldata/item_common.h"
#include "../xldata/item_routing.h"
#include "../xldata/item_socket.h"
#include "../xldata/setitem.h"

#include "../NResource/Static.h"

namespace ProjectZ { namespace NLogic {

static int s_index = 1;

Item::Item() : _itemSeq(0), _user(NULL), _status(0), e_EquipPos(ITEM_EQUIP_POS_NONE)
//, _quickSlotIndex(-1)
{
}

Item::~Item()
{
}

void
Item::Initialize()
{
	e_EquipPos = ITEM_EQUIP_POS_NONE;
	_itemSeq = 0;
	_user = NULL;
	_status = 0;
	//_quickSlotIndex = -1;
}

void
Item::Finalize()
{

}

Item::Data &
Item::GetData() { return _data; }


// from channel
bool
Item::Open_Normal(const Data & data, User * pUser)
{
	_data = data;
	_user = pUser;

//	_data.bag_type 		= getItemBagType();
//	_data.cur_duration 	= getItemDurability();
//	_data.max_duration	= getItemDurability();
//	_data.level			= getItemLevel();
//	this->setEffect();

	// normal item 에 경우 여기서 데이터 셋팅을 진행 하자.....
	return NResource::Static::Instance().GetItemResource()->SetItemDataFromResource(_user, _data);
}

void
Item::Open_Fairy(const Data & data, User * pUser)
{
	_data = data;
	_user = pUser;
}


// from database
void
Item::Open_FromDatabase(uint64_t itemSeq, const Data & data, User * pUser)
{
	_data = data;
	_user = pUser;
	_itemSeq = itemSeq;
}

void
Item::Open_None(const Data & data, User * pUser)
{
	_data = data;
	_user = pUser;
}

void
Item::Open_UpStone(const Data & data, User * pUser)
{
	_data = data;
	_user = pUser;

	NResource::Static::Instance().GetItemResource()->SetAdditionalEffect(_data);
}

void
Item::Open_DungeonDrop(const Data & data, User * pUser)
{
	_data = data;
	_user = pUser;
	_itemSeq = s_index++;

	NResource::Static::Instance().GetItemResource()->SetItemDataFromResource(_user, _data);
}

void
Item::SetEquip(EnumItemEquipPosition eEquipPos)
{
	e_EquipPos = eEquipPos;
}

EnumItemEquipPosition
Item::GetEquipPos()
{
	return e_EquipPos;
}

bool
Item::IsEquip()
{
	if (EnumItemEquipPosition::ITEM_EQUIP_POS_NONE == e_EquipPos)
		return false;

	return true;
}

uint64_t
Item::GetItemSeq() { return _itemSeq; }

bool
Item::InsertToDatabaseItemInfo(int slotIndex)
{
	int characterseq = 0;
	if (slotIndex == -1)
		characterseq = _user->GetCharacterInfo().characterseq;
	else
		characterseq = _user->GetCharacterInfoFromIndex(slotIndex).characterseq;


	if (1 != NResource::Static::Instance().GetItemResource()->getItemStackType(_data) && _data.quantity > 1)
	{
		DEBUGLOG("STACKOVER NO STACK ITEM STACK COUNT : %d, USER SEQ : %d", _data.quantity, _user->GetUserSeq());
		_data.quantity = 1;
	}

	if (1 == NResource::Static::Instance().GetItemResource()->getItemStackType(_data) && _data.quantity > 99)
	{
		DEBUGLOG("STACKOVER STACK ITEM STACK COUNT : %d, USER SEQ : %d", _data.quantity, _user->GetUserSeq());
		_data.quantity = 99;
	}


	::Database::Command::Auto clsAuto(::Database::GETCOMMANDPOOL());
	clsAuto->SetQueryType(::Database::Command::INSERT);
	clsAuto->MakeQuery("INSERT INTO info_item VALUES (NULL,%d,%d,0,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%lld)",
			_user->GetUserSeq()
			,characterseq
			,_data.bag_type
			,_data.bag_slot_number
//			,_data.stack_num
			,_data.quantity
			,_data.class_type
			,_data.sub_type
			,_data.tid
			,_data.iconidx
			,_data.item_type
			,_data.cur_duration
			,_data.max_duration
			,_data.set_type
			,_data.non_identity
			,_data.cur_refine_step
			,_data.quality
			,_data.level
			,_data.eff_type[0]
			,_data.eff_pos[0]
			,_data.eff_value[0]
			,_data.eff_type[1]
			,_data.eff_pos[1]
			,_data.eff_value[1]
			,_data.eff_type[2]
			,_data.eff_pos[2]
			,_data.eff_value[2]
			,_data.eff_type[3]
			,_data.eff_pos[3]
			,_data.eff_value[3]
			,_data.eff_type[4]
			,_data.eff_pos[4]
			,_data.eff_value[4]
			,_data.eff_type[5]
			,_data.eff_pos[5]
			,_data.eff_value[5]
			,_data.eff_type[6]
			,_data.eff_pos[6]
			,_data.eff_value[6]
			,_data.open_upgrade_stone_slot
			,_data.ability_enhance_rate
			,_data.max_enhance_step
			,_data.buy_use
			,_data.evolve_step
			,_data.evolve_max
			,_data.evolve_point
			,_data.evolve_percent
			,_data.evolve_value
			,_data.reg_date
			);
	if (false == ::Database::GETSESSION()->SyncExecute(_user->GetUserInfo().shard_Item_db_type, clsAuto))
		return false;

	if( clsAuto->GetErrorIdx() != 0 )
		return false;

	_itemSeq = clsAuto->GetInsertId();


	// Item Create

	return true;
}

bool
Item::UpdateDatabaseItemInfo()
{
	::Database::Command::Auto clsAuto(::Database::GETCOMMANDPOOL());
	clsAuto->SetQueryType(::Database::Command::UPDATE);
	clsAuto->MakeQuery("UPDATE info_item"
			" SET status = %d"
			" ,character_seq = %d"
			" ,bag_type = %d"
			" ,bag_slot_number = %d"
			" ,stack_num = %d"
			" ,class_type = %d"
			" ,sub_type = %d"
			" ,tid = %d"
			" ,iconidx = %d"
			" ,item_type = %d"
			" ,cur_duration = %d"
			" ,max_duration = %d"
			" ,set_type = %d"
			" ,non_identity = %d"
			" ,cur_refine_step = %d"
			" ,quality = %d"
			" ,level = %d"
			" ,eff_type0 = %d"
			" ,eff_pos0 = %d"
			" ,eff_value0 = %d"
			" ,eff_type1 = %d"
			" ,eff_pos1 = %d"
			" ,eff_value1 = %d"
			" ,eff_type2 = %d"
			" ,eff_pos2 = %d"
			" ,eff_value2 = %d"
			" ,eff_type3 = %d"
			" ,eff_pos3 = %d"
			" ,eff_value3 = %d"
			" ,eff_type4 = %d"
			" ,eff_pos4 = %d"
			" ,eff_value4 = %d"
			" ,eff_type5 = %d"
			" ,eff_pos5 = %d"
			" ,eff_value5 = %d"
			" ,eff_type6 = %d"
			" ,eff_pos6 = %d"
			" ,eff_value6 = %d"
			" ,open_upgrade_stone_slot = %d"
			" ,ablity_enhance_rate = %d"
			" ,max_enhance_step = %d"
			" ,buy_use = %d"
			" ,evolve_step = %d"
			" ,evolve_max = %d"
			" ,evolve_point = %d"
			" ,evolve_eff = %d"
			" ,evolve_eff_value = %d"
			" ,reg_date = %lld"
			" WHERE seq = %lld",
			_status
			,_user->GetCharacterInfo().characterseq
			,_data.bag_type
			,_data.bag_slot_number
			,_data.quantity
			,_data.class_type
			,_data.sub_type
			,_data.tid
			,_data.iconidx
			,_data.item_type
			,_data.cur_duration
			,_data.max_duration
			,_data.set_type
			,_data.non_identity
			,_data.cur_refine_step
			,_data.quality
			,_data.level
			,_data.eff_type[0]
			,_data.eff_pos[0]
			,_data.eff_value[0]
			,_data.eff_type[1]
			,_data.eff_pos[1]
			,_data.eff_value[1]
			,_data.eff_type[2]
			,_data.eff_pos[2]
			,_data.eff_value[2]
			,_data.eff_type[3]
			,_data.eff_pos[3]
			,_data.eff_value[3]
			,_data.eff_type[4]
			,_data.eff_pos[4]
			,_data.eff_value[4]
			,_data.eff_type[5]
			,_data.eff_pos[5]
			,_data.eff_value[5]
			,_data.eff_type[6]
			,_data.eff_pos[6]
			,_data.eff_value[6]
			,_data.open_upgrade_stone_slot
			,_data.ability_enhance_rate
			,_data.max_enhance_step
			,_data.buy_use
			,_data.evolve_step
			,_data.evolve_max
			,_data.evolve_point
			,_data.evolve_percent
			,_data.evolve_value
			,_data.reg_date
			,_itemSeq);

	if (false == ::Database::GETSESSION()->SyncExecute(_user->GetUserInfo().shard_Item_db_type, clsAuto))
		return false;

	if( clsAuto->GetErrorIdx() != 0 )
		return false;

	return true;
}

bool
Item::DeleteDatabaseItemInfo(ItemStatus eStatus)
{
	::Database::Command::Auto clsAuto(::Database::GETCOMMANDPOOL());
	clsAuto->SetQueryType(::Database::Command::UPDATE);
	clsAuto->MakeQuery("UPDATE info_item SET status = %d WHERE seq = %ld", static_cast<int>(eStatus), _itemSeq);

	if (false == ::Database::GETSESSION()->SyncExecute(_user->GetUserInfo().shard_Item_db_type, clsAuto))
		return false;

	if( clsAuto->GetErrorIdx() != 0 )
		return false;

	NLogic::Static::InstancePtr()->DEL_ITEM(this);

	// Item 삭제

	return true;
}

void
Item::WriteToPacket(::Network::Packet *packet)
{
	packet->MsgCat("%c", _data.cur_duration);
	packet->MsgCat("%c", _data.max_duration);
	packet->MsgCat("%c", _data.quantity);
	packet->MsgCat("%c", _data.set_type);
	packet->MsgCat("%c", _data.non_identity);
	packet->MsgCat("%c", _data.cur_refine_step);

	packet->MsgCat("%c", _data.quality);
	packet->MsgCat("%c", _data.level);

	for( int i=0 ; i<7 ; i++ )
	{
		packet->MsgCat("%c", _data.eff_type[i]);
		packet->MsgCat("%c", _data.eff_pos[i]);

		if (0 == i && ITEM_EQUIP_POS_NAME_TAG == NResource::Static::InstancePtr()->GetItemResource()->GetItemSubType(_data))
		{
			int remainTime = (_data.reg_date + (_data.eff_value[0] * 60)) - time(NULL);

			if (0 < remainTime)
				packet->MsgCat("%2d", remainTime / 60);
			else
				packet->MsgCat("%2d", 0);
		}
		else if (0 == i && ITEM_EQUIP_POS_NAME_TAG_WORLDBOSS == NResource::Static::InstancePtr()->GetItemResource()->GetItemSubType(_data))
		{
			int remainTime = (_data.reg_date + (_data.eff_value[0] * 60)) - time(NULL);

			if (0 < remainTime)
				packet->MsgCat("%2d", remainTime / 60);
			else
				packet->MsgCat("%2d", 0);
		}
		else
		{
			packet->MsgCat("%2d", _data.eff_value[i]);
		}
	}

	packet->MsgCat("%c", _data.open_upgrade_stone_slot);
	packet->MsgCat("%c", _data.ability_enhance_rate);
	packet->MsgCat("%c", _data.max_enhance_step);
	packet->MsgCat("%c", _data.buy_use);

	packet->MsgCat("%c", _data.evolve_step);
	packet->MsgCat("%c", _data.evolve_max);
	packet->MsgCat("%2d", _data.evolve_point);
	packet->MsgCat("%2d", _data.evolve_percent);
	packet->MsgCat("%2d", _data.evolve_value);
	packet->MsgCat("%c", _data.class_type);
	packet->MsgCat("%c", _data.sub_type);
	packet->MsgCat("%2d", _data.tid);
}

void
Item::SetStatus(int status)
{
	_status = status;
}

int
Item::GetStaus()
{
	return _status;
}

void
Item::ChangeBagTypeFromResourceData()
{
	_data.bag_type = NResource::Static::Instance().GetItemResource()->GetItemBagType(_data);
}

void
Item::ChangeBagTypeWareHouse()
{
	_data.bag_type = static_cast<int>(BAG_TYPE_WAREHOUSE);
}

void
Item::ChangeIdentifyItem()
{
	_data.non_identity = 0;
}

void
Item::DecreaseBattlepetStamina()
{
	/*
	 * PVP, 배틀로얄 입장 시 전투펫 스태미너 감소
	 */
	if (_data.eff_value[5] <= 0)
		return;

	_data.eff_value[5] -= 1;
	UpdateDatabaseItemInfo();
}

//
//bool
//Item::IsQuickSlot()
//{
//	if (-1 != _quickSlotIndex)
//		return true;
//
//	return false;
//}

} /*NLogic*/ } /* namespace ProjectZ */
